﻿using System;
using System.Windows.Forms;
using System.Drawing;
using System.Text;
using System.Diagnostics;
using System.Configuration;
using Test_Operator_Platform.Common;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using System.Runtime.InteropServices;
using WinLibrary.Security;
using System.Threading.Tasks;
using WinLibrary.JsonManage;
using FigKey_TestExec_SL.Common;
using FigKey_TestExec_SL.Entity;
using FigKey_TestExec_SL.FkEnum;
using FigKey_TestExec_SL.View;
using FigKey_TestExec_SL.Test;
using WinLibrary.XString;
using WinLibrary.Messages;
using WinLibrary.TimerPlan;
using WinLibrary.UserControls;
using WinLibrary.Controls;
using WinLibrary.FileOperate;
using DataModels;
using FKDatabase;
using System.Threading;
using Test_Operator_Platform.Model;
using Test_Operator_Platform.Test;

namespace Test_Operator_Platform.UI
{
    public partial class TestOperatorPlatform : Form
    {
        public delegate void NotificationEvents(bool status, bool modeUpdate, string message);
        public event NotificationEvents NotificationHandlers;
        public string currentPartNumber;

        public void Notification(bool status, bool modeUpdate, string message)
        {
            if (NotificationHandlers == null)
                return;
            NotificationHandlers(status, modeUpdate, message);
        }
        FKBasicEntity basicEntity;
        AutoSizeFormClass autoSizeForm;
        string _localCfgFile;
        StringBuilder testPlanData = new StringBuilder();
        FrmReport frmReport;
        TreeViewEx treeView;//加载测试计划容器
        TestPlanWork tpWork;
        SNLabelEntity snEntity;
        string snTestCatchFile = "";//LMS
        public bool CloseForm = false;

        string user;
        //bool autoTestFlag;//启动自动测试循环标志
        bool IsRunning;
        public Device device;
        int cycleTime = 0;
        bool debugTest;
        List<TestSequences> testSequences;

        public TestOperatorPlatform(string user, SNLabelEntity entity, TestPlanWork pwork, ref Device dev)
        {
            InitializeComponent();
            this.user = user;
            this.snEntity = entity;
            this.device = dev;
            this.tpWork = pwork;
            this.dataGridView1.DoubleBufferedDataGirdView(true);
        }

        /// <summary>
        /// 防止窗体改变大小时闪烁
        /// </summary>
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;
                return cp;
            }
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            Init();
            DataViewUtils.InitDataGrid(this.dataGridView1);
            this.autoSizeForm.ControllInitializeSize(this);

            this.btn_run.Click += Btn_run_Click;
            this.btn_pause.Click += Btn_pause_Click;
            this.btn_stop.Click += Btn_stop_Click;
            this.dataGridView1.SelectionChanged += DataGridView1_SelectionChanged;

            this.SizeChanged += TestOperatorPlatform_SizeChanged;
            GridViewHelper.MessageHandler += TpWork_MessageHandler;
            this.tbCycleTime.MouseLeave += TbCycleTime_MouseLeave;
            this.cbPartNumber.SelectedIndexChanged += CbPartNumber_SelectedIndexChanged;

            this.tpWork.TestRecordCallBack += TpWork_TestRecordCallBack;
            LoadTestPlan();
        }

        private void TpWork_TestRecordCallBack(TestRecordData tData)
        {
            UpdateUI.UpdateTestUI(tData, this.dataGridView1);
        }

        private void CbPartNumber_SelectedIndexChanged(object sender, EventArgs e)
        {
            var tplan = this.cbPartNumber.Text;
            if (string.IsNullOrEmpty(tplan))
                return;
            SelectCurrentPlans(tplan);
        }

        private void TbCycleTime_MouseLeave(object sender, EventArgs e)
        {
            int cycleTime = 0;
            if (!int.TryParse(this.tbCycleTime.Text.Trim(), out cycleTime))
            {
                MessageBox.Show("The Cycle Time is invalid！", "Error");
                this.tbCycleTime.Focus();
                this.tbCycleTime.ForeColor = Color.Red;
                return;
            }
            else
            {
                this.tbCycleTime.ForeColor = Color.Black;
            }
            this.basicEntity.TestCycle = cycleTime;
            ModifyTestCycle();
        }

        private void TimerModbus_Tick(object sender, EventArgs e)
        {
            CheckModbusCommucation();
        }

        private void TpWork_MessageHandler(GridViewHelper.MessageType msgType, string message, Color color)
        {
            switch (msgType)
            {
                case GridViewHelper.MessageType.MessageInfo:
                    {
                        UpdateTestStatus(this.lbMessage, message, color);//错误消息
                        break;
                    }
                case GridViewHelper.MessageType.FilePath:
                    {
                        if (string.IsNullOrEmpty(message))
                        {
                            this.img_product.Image = null;
                        }
                        else
                        {
                            if (System.IO.File.Exists(message))
                            {
                                this.img_product.Image = Image.FromFile(message);
                            }
                        }
                        break;
                    }
                case GridViewHelper.MessageType.BarCode:
                    {
                        LogHelper.Log.Info("收到条码：" + message);
                        UpdateSerialNumber(message);
                        this.basicEntity.SerialNumber = message;
                        break;
                    }
            }
        }

        private void UpdateSerialNumber(string message)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(() =>
                {
                    this.tbSerialNumber.Text = message;
                }));
            }
            else
            {
                this.tbSerialNumber.Text = message;
            }
        }

        private void TestOperatorPlatform_SizeChanged(object sender, EventArgs e)
        {
            this.autoSizeForm.ControlAutoSize(this);
            DataViewUtils.SetGridAdapter(this.dataGridView1);
        }

        private void DataGridView1_SelectionChanged(object sender, EventArgs e)
        {
            var currentRow = this.dataGridView1.CurrentRow;
            if (currentRow == null)
                return;
            if (currentRow.Cells[0] == null)
                return;
            var color = currentRow.DefaultCellStyle.BackColor;
            if (color == Color.Red)
                currentRow.DefaultCellStyle.SelectionBackColor = Color.Red;
        }

        private void Btn_exist_Click(object sender, EventArgs e)
        {
            if (FormShowBox.MessageExitBox() != DialogResult.Yes)
                return;
            Environment.Exit(0);
        }

        private void Btn_language_Click(object sender, EventArgs e)
        {

        }

        public void OpenReport()
        {
            Observer.SendMessage(this, this.testPlanData);
            if (this.frmReport.ShowDialog() == DialogResult.OK)
            {

            }
        }

        private void Btn_stop_Click(object sender, EventArgs e)
        {
            TestStop(true);
        }

        private void TestStop(bool show)
        {
            this.tbCycleTime.Enabled = true;
            this.tpWork.StopTest(null);
            this.device.IsAutoMode = false;//停止自动测试，初始化时重新获取
            this.btn_run.Enabled = true;
            this.btn_pause.Enabled = false;
            this.btn_stop.Enabled = false;
            if (show)
            {
                UpdateTestStatus(this.lbMessage, "Tests stopped", this.tpWork.GetWarnColor());
            }
        }

        private void DebugTestStop()
        {
            this.tpWork.StopTest(null);//停止当前测试
            this.tpWork.changeTypeTest = true;//执行新任务

            LogHelper.Log.Info($"设置后-startAutoTest={this.tpWork.startAutoTest}-ctype={this.tpWork.changeTypeTest}");
        }

        private void Btn_pause_Click(object sender, EventArgs e)
        {
            IsRunning = false;
            this.tpWork.PauseTest(null);
            this.btn_pause.Enabled = false;
            this.btn_run.Enabled = true;
            UpdateTestStatus(this.lbMessage, "Tests paused", this.tpWork.GetWarnColor());
        }

        private void Btn_run_Click(object sender, EventArgs e)
        {
            AutoStartTest();
        }

        private void AutoStartTest()
        {
            InitTest();
            StartTest();
        }

        /// <summary>
        /// 重置样件状态，有样件测试需求时使用
        /// </summary>
        private void ResetSampleState(bool sampleTest)
        {
            if (!sampleTest)
                return;
            if (this.device.IsAutoMode)
            {
                //this.debugTest = true;
                if (this.debugTest)
                {
                    var debugResult = Database.QueryDebugProduct(this.currentPartNumber);
                    ResetSampleSN(debugResult);//重置所有样件状态
                    LogHelper.Log.Info("已重置所有样件状态！");
                }
            }
        }

        private void UseAtutoTest()
        {
            InitTest();
        }

        private void InitTest()
        {
            this.tbCycleTime.Enabled = false;

            #region 获取自动测试配置
            Notification(false, true, "");
            #endregion

            #region 测试周期时间
            if (!int.TryParse(this.tbCycleTime.Text.Trim(), out cycleTime))
            {
                MessageBox.Show("The Cycle Time is invalid！", "Error");
                this.tbCycleTime.Focus();
                this.tbCycleTime.ForeColor = Color.Red;
                return;
            }
            else
            {
                this.tbCycleTime.ForeColor = Color.Black;
            }

            cycleTime = cycleTime * 1000;
            #endregion

            #region 使用样件测试
            this.debugTest = true;
            if (ConfigurationManager.AppSettings["debugAutoTest"] != null)
            {
                if (ConfigurationManager.AppSettings["debugAutoTest"].ToString().ToLower().Trim() == "false")
                {
                    this.debugTest = false;
                }
            }
            ResetSampleState(this.debugTest);
            #endregion

            //初始化数据库配置等
            Database.InitDatabase();
            this.basicEntity.Sequences = Database.QuerySequences();
            double cacheTime = 36500;
            if (ConfigurationManager.AppSettings["cacheTime"] != null)
            {
                if (!double.TryParse(ConfigurationManager.AppSettings["cacheTime"].ToString(), out cacheTime))
                {
                    //失败
                    cacheTime = 36500;//天
                }
            }
            this.basicEntity.CacheTime = cacheTime;
            this.testSequences = this.tpWork.AddTestPlanCache(this.basicEntity);
        }

        private void StartTest()
        {
            int i = 0;
            int debugCount = 0;
            bool firstTest = true;
            Task.Run(() =>
            {
                while (true)
                {
                    if (this.CloseForm)
                        break;

                    //手动模式
                    if (!this.device.IsAutoMode)
                    {
                        if (!CheckTestProduct(this.lbxTestPlan.Text))
                        {
                            return;
                        }
                        if (!CheckDevice(this.lbxTestPlan.Text))
                        {
                            return;
                        }
                        RunTest();
                        return;
                    }

                    //自动模式
                    if (!CheckTestProduct(this.lbxTestPlan.Text))
                    {
                        continue;
                    }
                    if (!CheckDevice(this.lbxTestPlan.Text))
                    {
                        continue;
                    }

                    //换型后，执行测试样件，测试OK进入自动测试
                    if (this.debugTest)
                    {
                        if (firstTest)
                        {
                            UpdateTestStatus(this.lbMessage, "进入调试模式，请准备测试样件！", Color.Red);
                            System.Threading.Thread.Sleep(1000);
                            UpdateTestStatus(this.lbMessage, "开始测试样件！", Color.Red);
                            firstTest = false;
                        }

                        UpdateTestStatus(this.lbMessage, $"测试样件！", Color.Red);
                        System.Threading.Thread.Sleep(1000);

                        //查询需要测试的样件，测试完成进行SN与结果对比，成功后才能进入正式测试
                        var debugResult = Database.QueryDebugProduct(this.currentPartNumber);

                        RunTest();
                        //调试模式还没完成时，处于等待中收到另外的换型通知或者结束通知

                        LogHelper.Log.Info("调试模式测试完成！");

                        if (!this.device.IsAutoMode)
                        {
                            LogHelper.Log.Info("未设置自动测试" + this.device.IsAutoMode);
                            return;//结束测试，如点击停止
                        }
                        else
                        {
                            LogHelper.Log.Info($"开始换型-startAutoTest={this.tpWork.startAutoTest}-ctype={this.tpWork.changeTypeTest}");
                            if (!this.tpWork.startAutoTest)//自动测试任务结束
                            {
                                //遇到换型指示，应停止当前任务，执行新的换型任务
                                if (this.tpWork.changeTypeTest)
                                {
                                    firstTest = true;
                                    this.tpWork.changeTypeTest = false;
                                    LogHelper.Log.Info("收到切换型号指令，开始执行！");
                                    UpdateTestStatus(this.lbMessage, "收到切换型号指令，开始执行！", Color.Lime);
                                    continue;
                                }
                            }
                        }
                        UpdateTestStatus(this.lbMessage, "调试模式测试完成，开始判断测试结果！", Color.Lime);
                        //比对条码
                        //MessageBox.Show(this.basicEntity.SerialNumber);

                        //查询满足条件他产品，多个产品按照测试次数计算是否测试完，测试人员可以不分顺序测试
                        var result = debugResult.Find(p => p.SerialNumber == this.basicEntity.SerialNumber && p.PartNumber == this.currentPartNumber);
                        if (result == null)
                        {
                            LogHelper.Log.Info($"当前样件与配置不匹配,{this.basicEntity.SerialNumber}");
                            UpdateTestStatus(this.lbMessage, "当前样件条码与配置不匹配！", Color.Red);
                            System.Threading.Thread.Sleep(1000);
                            firstTest = true;//继续进行调试模式测试
                            continue;
                        }
                        else
                        {
                            //比对结果
                            if (result.TestResult != this.btnResult.Text)
                            {
                                LogHelper.Log.Info($"当前样件结果与配置不匹配,{this.btnResult.Text}");
                                UpdateTestStatus(this.lbMessage, "当前样件结果与配置不匹配！", Color.Red);
                                System.Threading.Thread.Sleep(1000);
                                firstTest = true;//继续进行调试模式测试
                                continue;
                            }
                        }

                        System.Threading.Thread.Sleep(1000);
                        Database.UpdateDebugProduct(result.PartNumber, result.SerialNumber, 1);
                        var fResult = CheckSampleSN(result.PartNumber);
                        LogHelper.Log.Info("样件结果：" + fResult);

                        debugCount++;
                        if (debugCount == debugResult.Count)
                        {
                            //调试模式测试结束
                            if (fResult)//查询样件是否都测试合格  调试模式成功
                            {
                                this.debugTest = false;
                                debugCount = 0;
                                LogHelper.Log.Info("样件测试全部完成，即将进入自动测试！！");
                                UpdateTestStatus(this.lbMessage, "样件测试全部完成，即将进入自动测试！", Color.Lime);
                                //MessageBox.Show("样件测试全部完成，即将进入自动测试！");
                                System.Threading.Thread.Sleep(5000);
                            }
                            else
                            {
                                this.Invoke(new Action(() => { this.btnResult.Text = "FAIL"; }));
                                UpdateTestStatus(this.lbMessage, $"{debugResult.Count}个测试样件测试失败！重新开始测试所有样件！", Color.Red);
                                System.Threading.Thread.Sleep(1000);
                            }
                            debugCount = 0;//重置计数
                        }
                        else
                        {
                            //只要是所有测试成功了都可以结束调试模式
                            if (fResult)//查询样件是否都测试合格  调试模式成功
                            {
                                this.debugTest = false;
                                debugCount = 0;
                                LogHelper.Log.Info("样件测试全部完成，即将进入自动测试！");
                                UpdateTestStatus(this.lbMessage, "样件测试全部完成，即将进入自动测试！", Color.Lime);
                                System.Threading.Thread.Sleep(5000);
                                //MessageBox.Show("样件测试全部完成，即将进入自动测试！");
                            }
                            else
                            {
                                LogHelper.Log.Info($"第{debugCount}个样件测试成功，开始下一个！");
                                UpdateTestStatus(this.lbMessage, $"第{debugCount}个样件测试成功，开始下一个！", Color.Red);
                                System.Threading.Thread.Sleep(1000);
                            }
                        }
                    }
                    else//没有调试程序的自动模式
                    {
                        //自动模式
                        //当切换型号-调试模式完成后也会进入
                        RunTest();

                        if (!this.tpWork.startAutoTest)//自动测试任务结束
                        {
                            //遇到换型指示，应停止当前任务，执行新的换型任务
                            if (this.tpWork.changeTypeTest)
                            {
                                firstTest = true;
                                debugCount = 0;
                                this.tpWork.changeTypeTest = false;
                                UseAtutoTest();
                                LogHelper.Log.Info("收到切换型号指令，开始执行！");
                                UpdateTestStatus(this.lbMessage, "收到切换型号指令，开始执行！", Color.Lime);
                                continue;
                            }
                        }
                    }

                    System.Threading.Thread.Sleep(1);//(this.cycleTime);
                    i++;
                }
            });
        }

        private void RunTest()
        {
            this.IsRunning = true;
            SetRunTestStatus(false);
            UpdateTestStatus(this.lbMessage, "Testing...", Color.Green);
            ClearTestResult();

            TestResult testResult = this.tpWork.TestAllDoWork(this.testSequences, this.basicEntity, this.dataGridView1, null);
            ButtonResultInvok(testResult.TestStatus);
            var sn = this.basicEntity.SerialNumber;
            var partNumber = SNCode.SNPartNumber(ref sn, this.snEntity);
            this.basicEntity.PartNumber = partNumber;

            testResult.SNumber = this.basicEntity.SerialNumber;
            testResult.PartNumber = partNumber;
            IsRunning = false;

            this.tpWork.TestComplete(null, testResult);//清空计数
            UpdateTestResullt(testResult);//计算
            if (!this.device.IsAutoMode)
            {
                IsRunning = false;//手动测试结束，全部结束
            }
            //test complete update
            testResult.PinCount = 0;
            testResult.PassCount = 0;
            testResult.FailCount = 0;
            UpdateTestStatus(this.lbMessage, "Tests completed", this.tpWork.GetCompleteColor());

            #region test result--本次产品测试成功/失败

            if (testResult.TestStatus == TestPlanStatus.Stop)//测试未完成，不计入
                return;
            this.basicEntity.TestTotal++;
            this.basicEntity.TestPinCount++;
            if (testResult.TestStatus == TestPlanStatus.Pass)
            {
                this.basicEntity.TestPassCount++;
            }
            else if (testResult.TestStatus == TestPlanStatus.Fail)
            {
                this.basicEntity.TestFailCount++;
            }
            #endregion

            #region Invok UI
            this.Invoke(new Action(() =>
            {
                this.lbxTestTime.Text = testResult.TestTime;
                UpdateTestCount(testResult.TestTime);
                SaveSNTestResult(this.tbSerialNumber.Text, partNumber, testResult.TestHistory.TestResult, testResult.TestHistory.TestNumber);

                if (this.basicEntity.TestTotal == 0)
                {
                    this.lbxPassPercent.Text = "0%";
                    this.lbxFailPercent.Text = "0%";
                }
                this.btn_stop.Enabled = true;
                this.tbCycleTime.Enabled = true;
                this.tbSerialNumber.Clear();//
            }));
            #endregion
        }

        private void SaveSNTestResult(string sn, string partNumber, string result, long testNumber)
        {
            if (string.IsNullOrEmpty(sn))
            {
                LogHelper.Log.Info("传入SN为空");
                return;
            }
            if (!System.IO.File.Exists(this.snTestCatchFile))
            {
                LogHelper.Log.Error("SNCatchFile-LMS不存在！");
                //File.Create(this.snTestCatchFile);
                return;
            }
            //如果测试结果失败，查询错误代码反馈
            var errCode = Database.QueryFaultCodes(testNumber);
            SaveTextFile(this.snTestCatchFile, $"{sn},{result},{errCode}");

            //this.snTestQueues.Enqueue(sn);//添加SN到队列
            //保存SN到本地目录
            TestWork.TestCompletedSave(this.basicEntity.TestLogPath, this.basicEntity.TestNumber, sn, partNumber, result);
        }

        public void SaveSNTestResult(StringBuilder sn)
        {
            if (sn.Length == 0)
            {
                LogHelper.Log.Error("SN长度为空！");
                return;
            }
            if (!System.IO.File.Exists(this.snTestCatchFile))
            {
                LogHelper.Log.Error("SNCatchFile-LMS不存在！");
                return;
            }
            SaveTextFile(this.snTestCatchFile, sn.ToString());
        }

        /// <summary>
        /// 保存测试SN到LMS映射路径
        /// </summary>
        /// <param name="file"></param>
        /// <param name="content"></param>
        private void SaveTextFile(string file, string content)
        {
            try
            {
                //LogHelper.Log.Info("开始保存，" + content);
                using (FileStream fs = new FileStream(file, FileMode.Append, FileAccess.Write))
                {
                    using (var sw = new StreamWriter(fs))
                    {
                        sw.WriteLine(content);
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.Log.Error(string.Format("Test写入文件出错：消息={0},堆栈={1}", ex.Message, ex.StackTrace));
            }
        }

        private void UpdateTestCount(string testTime)
        {
            #region 更新所有测试记录结果  累计
            this.lbxTotal.Text = this.basicEntity.TestTotal + "";
            this.lbxPinCount.Text = this.basicEntity.TestPinCount + "";
            this.lbxPassCount.Text = this.basicEntity.TestPassCount + "";
            this.lbxFailCount.Text = this.basicEntity.TestFailCount + "";
            this.lbxPassPercent.Text = ((((float)this.basicEntity.TestPassCount / (float)this.basicEntity.TestTotal)) * 100).ToString("f1") + "%";
            this.lbxFailPercent.Text = ((((float)this.basicEntity.TestFailCount / (float)this.basicEntity.TestTotal)) * 100).ToString("f1") + "%";

            if (this.basicEntity.TestPassCount > 0)
            {
                if (this.basicEntity.TestPassCount == this.basicEntity.TestTotal)
                {
                    this.lbxPassPercent.Text = "100%";
                }
            }
            else
            {
                this.lbxPassPercent.Text = "0%";
            }

            if (this.basicEntity.TestFailCount > 0)
            {
                if (this.basicEntity.TestFailCount == this.basicEntity.TestTotal)
                {
                    this.lbxFailPercent.Text = "100%";
                }
            }
            else
            {
                this.lbxFailPercent.Text = "0%";
            }
            #endregion
        }

        /// <summary>
        /// 更新当前测试的结果
        /// </summary>
        /// <param name="currentResult"></param>
        private void UpdateTestResullt(TestResult currentResult)
        {
            #region 更新当前测试结果
            if (currentResult != null)
            {
                if (currentResult.PassCount > 0)
                {
                    if (currentResult.PassCount == currentResult.TestTotal)
                    {
                        this.btnResult.Text = "PASS";
                        this.btnResult.BackColor = Color.Green;
                        this.btnResult.ForeColor = Color.White;
                    }
                    else
                    {
                        this.btnResult.Text = "FAIL";
                        this.btnResult.BackColor = Color.Red;
                        this.btnResult.ForeColor = Color.White;
                    }
                }
                else
                {
                    if (currentResult.FailCount > 0)
                    {
                        this.btnResult.Text = "FAIL";
                        this.btnResult.BackColor = Color.Red;
                        this.btnResult.ForeColor = Color.White;
                    }
                }
            }
            #endregion

            #region 保存测试计数结果,累计计数与当前测试结果、测试时间
            TbTestResult tResult = new TbTestResult();
            tResult.TestAmassTotal = this.basicEntity.TestTotal;
            tResult.TestAmassPass = this.basicEntity.TestPassCount;
            tResult.TestAmassFail = this.basicEntity.TestFailCount;
            tResult.TestAmassPinCount = this.basicEntity.TestPinCount;
            tResult.TestCycleResult = this.btnResult.Text;
            if (string.IsNullOrEmpty(tResult.TestCycleResult))
                tResult.TestCycleResult = "";
            tResult.TestCycleTime = currentResult.TestTime;

            Database.UpdateTestResult(tResult);
            #endregion
        }

        private void ButtonResultInvok(TestPlanStatus status)
        {
            this.Invoke(new Action(() =>
            {
                switch (status)
                {
                    case TestPlanStatus.Pass:
                        {
                            this.btn_run.Enabled = true;
                            this.btn_pause.Enabled = false;
                            this.btn_stop.Enabled = false;
                            break;
                        }
                    case TestPlanStatus.Fail:
                        {
                            this.btn_run.Enabled = true;
                            this.btn_pause.Enabled = false;
                            this.btn_stop.Enabled = true;
                            break;
                        }
                    default:
                        {
                            this.btn_run.Enabled = true;
                            this.btn_pause.Enabled = false;
                            this.btn_stop.Enabled = true;
                            break;
                        }
                }
            }));
        }

        private void ClearTestResult()
        {
            this.Invoke(new Action(() =>
            {
                this.dataGridView1.Rows.Clear();
                this.btnResult.BackColor = Color.Transparent;
                this.btnResult.Text = "Testing";
                this.btnResult.ForeColor = Color.LightGreen;
            }));
        }

        private void Btn_loadTestplan_Click(object sender, EventArgs e)
        {
            ReadTestPlan();
        }

        public void ReadTestPlan()
        {
            FrmLoadTestplan frm = new FrmLoadTestplan(ref this.basicEntity, this._localCfgFile);
            if (frm.ShowDialog() == DialogResult.OK)
            {
                TestStop(false);//先停止，防止当前有未结束的任务又重新开始
                LoadTestPlan();
            }
        }

        private void LoadTestPlan()
        {
            string id;
            string testPlan, tpid, sequence;
            //加载Main序列
            if (!System.IO.File.Exists(this.basicEntity.TestActualProfile))
            {
                LogHelper.Log.Error("打开测试计划失败，文件路径不存在！" + this.basicEntity.TestActualProfile);
                return;
            }
            var result = XmlOperate.LoadXMLData(this.treeView, this.basicEntity.TestActualProfile, "Main", out id, out testPlan, out tpid, out sequence);
            if (!result)
                return;
            this.basicEntity.TestPlanPath = id;
            //显示Main序列测试项，加载所有，只显示带有LIMIT的测试项

            //添加缓存
            //this.testSequences = this.tpWork.AddTestPlanCache(this.basicEntity);

            //保存选择的当前测试测试计划配置
            ConfigManage.SaveConfig(this.basicEntity, this._localCfgFile);

            this.currentPartNumber = testPlan;
            this.lbxTestPlan.Text = testPlan;
            this.cbPartNumber.Text = testPlan;
            this.btn_run.Enabled = true;
            this.btn_stop.Enabled = false;
            Notification(true, false, "");
        }

        /// <summary>
        /// 从PartNumber列表选择测试计划
        /// </summary>
        /// <param name="testPlan"></param>
        private void SelectCurrentPlans(string testPlan)
        {
            var currentPlanPath = this.basicEntity.TestActualProfile;
            var currentDirectory = Path.GetDirectoryName(currentPlanPath);
            if (!System.IO.Directory.Exists(currentDirectory))
                return;
            DirectoryInfo dirs = new DirectoryInfo(currentDirectory);
            var files = dirs.GetFiles();
            this.basicEntity.TestPlanList = new List<string>();
            foreach (var file in files)
            {
                var tp = Path.GetFileNameWithoutExtension(file.Name);
                if (tp == testPlan.Trim())
                {
                    this.basicEntity.TestActualProfile = file.FullName;
                    LoadTestPlan();
                    break;
                }
                this.basicEntity.TestPlanList.Add(file.FullName);
            }
        }

        private void Init()
        {
            this.treeView = new TreeViewEx();
            this.basicEntity = new FKBasicEntity();
            this.autoSizeForm = new AutoSizeFormClass();
            this.frmReport = new FrmReport();

            this._localCfgFile = System.Environment.CurrentDirectory + "\\config\\";
            if (!System.IO.Directory.Exists(this._localCfgFile))
                System.IO.Directory.CreateDirectory(this._localCfgFile);
            this._localCfgFile = this._localCfgFile + "fktestsl.config";

            var config = ConfigManage.ReadConfig(this._localCfgFile);
            if (config != null)
            {
                this.basicEntity = config;
            }
            else
            {
                LogHelper.Log.Error("读取配置失败");
            }
            this.basicEntity.VariableType = VariableType.TestStepParms.ToString();

            var tResult = Database.QueryTestResult();
            if (tResult != null)
            {
                if (tResult.TestAmassTotal != null)
                {
                    this.basicEntity.TestTotal = (long)tResult.TestAmassTotal;
                }
                else
                {
                    LogHelper.Log.Error("读取配置结果异常！");
                }
                if (tResult.TestAmassPinCount != null)
                {
                    this.basicEntity.TestPinCount = (long)tResult.TestAmassPinCount;
                }
                if (tResult.TestAmassPass != null)
                {
                    this.basicEntity.TestPassCount = (long)tResult.TestAmassPass;
                }
                if (tResult.TestAmassFail != null)
                {
                    this.basicEntity.TestFailCount = (long)tResult.TestAmassFail;
                }
            }
            if (ConfigurationManager.AppSettings["LMS_SN_TEST_FILE"] != null)
                this.snTestCatchFile = ConfigurationManager.AppSettings["LMS_SN_TEST_FILE"].ToString();

            UpdateTestCount("");//更新最新的测试

            bool cycleTmVisible = false;
            var testCycleVisible = System.Configuration.ConfigurationManager.AppSettings["testCycleVisible"];
            if (testCycleVisible != null)
            {
                if (testCycleVisible.ToString().ToLower() == "true")
                {
                    cycleTmVisible = true;
                }
            }

            this.tbCycleTime.Visible = cycleTmVisible;
            this.lbxCycleTm.Visible = cycleTmVisible;
            this.lbxCycleTmUnit.Visible = cycleTmVisible;
        }

        private void SetRunTestStatus(bool b)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(() =>
                {
                    this.btn_run.Enabled = b;
                    this.btn_pause.Enabled = !b;
                    this.btn_stop.Enabled = !b;
                }));
            }
            else
            {
                this.btn_run.Enabled = b;
                this.btn_pause.Enabled = !b;
                this.btn_stop.Enabled = !b;
            }
        }

        private void CheckModbusCommucation()
        {
            var visaClient = Database.QueryVisaClient();
            if (visaClient != null)
            {
                if (!visaClient[0].Connected)
                {
                    this.plModbus.BackColor = Color.Red;
                }
                else
                {
                    if (string.IsNullOrEmpty(visaClient[0].MESModbusRead))
                    {
                        this.plModbus.BackColor = Color.Yellow;
                    }
                    else
                    {
                        this.plModbus.BackColor = Color.Lime;
                    }
                }
            }
        }

        private void UpdateTestStatus(Label lb, string message, System.Drawing.Color color)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(() =>
                {
                    lb.Text = message;
                    lb.ForeColor = color;
                }));
            }
            else
            {
                lb.Text = message;
                lb.ForeColor = color;
            }
        }

        /// <summary>
        /// 检查型号是否匹配
        /// </summary>
        /// <param name="partNumber"></param>
        /// <returns></returns>
        private bool CheckTestProduct(string partNumber)
        {
            //是否验证型号
            if (ConfigurationManager.AppSettings["checkPartNumber"] != null)
            {
                if (ConfigurationManager.AppSettings["checkPartNumber"].ToString().ToLower() == "false")
                    return true;
            }

            //验证型号
            if (partNumber != this.currentPartNumber)
            {
                UpdateTestStatus(this.lbMessage, $"测试型号不匹配，请用型号{this.currentPartNumber}的产品测试！", Color.Red);
                return false;
            }
            return true;
        }

        /// <summary>
        /// 测试前检查夹具是否正常
        /// </summary>
        private bool CheckDevice(string partNumber)
        {
            if (ConfigurationManager.AppSettings["checkDevice"] != null)
            {
                if (ConfigurationManager.AppSettings["checkDevice"].ToString().ToLower() == "false")
                    return true;
            }

            this.Invoke(new Action(()=> { this.btn_run.Enabled = false; }));
            var pCmd = ConfigurationManager.AppSettings[$"{partNumber}"];
            if (pCmd == null)
            {
                UpdateTestStatus(this.lbMessage, "读取夹具配置错误！", Color.Red);
                return false;
            }
            int timeout = 1000;
            if (ConfigurationManager.AppSettings["checkDevTimeout"] != null)
                int.TryParse(ConfigurationManager.AppSettings["checkDevTimeout"], out timeout);

            var result = ReadDeviceState(timeout);//读取夹具状态
            //LogHelper.Log.Info("读取夹具指令：" + result);

            if (string.IsNullOrEmpty(result))
            {
                this.Invoke(new Action(()=> { this.btn_stop.Enabled = true; }));
                UpdateTestStatus(this.lbMessage, "读取夹具状态超时！请重新执行！", Color.Red);
                return false;
            }
            var resArr = result.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            if (resArr.Length < 6)
            {
                //LogHelper.Log.Error($"读取夹具状态数据长度不足！" + result);
                return false;
            }
            //73 - 02 02 02 00 40 FC 48要40 不等于40提示家具错误
            //检查夹具是否匹配,p=17040875-02,cfg=02 02 02 00 28 FD A6,cur=28
            //75 - 02  20  提示夹具错误

            LogHelper.Log.Info($"检查夹具是否匹配,p={partNumber},cfg={result},cur={resArr[4]}");

            var pResult = pCmd.ToString().Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries);
            if (pResult.Length == 1)
            {
                var oriValue = Convert.ToInt32(pResult[0], 16);
                if ((oriValue & Convert.ToInt32(resArr[4], 16)) != oriValue)
                {
                    //提示界面夹具错误
                    UpdateTestStatus(this.lbMessage, "夹具错误！", Color.Red);
                    return false;
                }
            }
            else if (pResult.Length == 2)
            {
                var oriValue = Convert.ToInt32(pResult[0], 16);
                if ((oriValue & Convert.ToInt32(resArr[4], 16)) != oriValue)
                {
                    //提示界面夹具错误
                    UpdateTestStatus(this.lbMessage, $"夹具错误！{pResult[1]}", Color.Red);
                    return false;
                }
            }
            else
            {
                UpdateTestStatus(this.lbMessage, $"夹具配置错误", Color.Red);
                return false;
            }

            return true;
        }

        private string ReadDeviceState(int timeout)
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();
            while (true)
            {
                if (watch.ElapsedMilliseconds >= timeout)
                {
                    return "";
                }
                string mResult;
                this.device.Instrument.InstrumentMulCltQuery(this.device.ModbusPort, 1, "02 02 00 00 00 10", 1, 250, 1, out mResult);
                if (!string.IsNullOrEmpty(mResult))
                    return mResult;
                System.Threading.Thread.Sleep(30);
            }
        }

        private void ResetSampleSN(List<TbDebugProduct> list)
        {
            for (int i = 0; i < list.Count; i++)
            {
                Database.UpdateDebugProduct(list[i].PartNumber, list[i].SerialNumber, 0);
            }
        }

        private bool CheckSampleSN(string partNumber)
        {
            var list = Database.QueryDebugProduct(partNumber);
            foreach (var v in list)
            {
                if (v.State == 0)
                {
                    return false;
                }
            }
            return true;
        }

        #region public method
        public void ClearTestCount()
        {
            this.basicEntity.TestTotal = 0;
            this.basicEntity.TestPassCount = 0;
            this.basicEntity.TestFailCount = 0;

            this.lbxTotal.Text = "0";
            this.lbxPassCount.Text = "0";
            this.lbxPassPercent.Text = "0%";
            this.lbxFailCount.Text = "0";
            this.lbxFailPercent.Text = "0%";

            ConfigManage.SaveConfig(this.basicEntity, this._localCfgFile);
        }

        public void ClearPinCount()
        {
            this.basicEntity.TestPinCount = 0;
            this.lbxPinCount.Text = "0";
            ConfigManage.SaveConfig(this.basicEntity, this._localCfgFile);
        }

        public void ModifyTestCycle()
        {
            ConfigManage.SaveConfig(this.basicEntity, this._localCfgFile);
        }

        public void UpdatePartNumbers(string[] pNumbers)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(() =>
                {
                    this.cbPartNumber.Items.Clear();
                    foreach (var pNum in pNumbers)
                    {
                        this.cbPartNumber.Items.Add(pNum);
                    }
                }));
            }
            else
            {
                this.cbPartNumber.Items.Clear();
                foreach (var pNum in pNumbers)
                {
                    this.cbPartNumber.Items.Add(pNum);
                }
            }
        }

        public void ChangePartNumber(string partNumber)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(() =>
                {
                    PNumLoadTestPlan(partNumber);
                }));
            }
            else
            {
                PNumLoadTestPlan(partNumber);
            }
        }

        /// <summary>
        /// 自动换型
        /// </summary>
        /// <param name="partNumber"></param>
        private void PNumLoadTestPlan(string partNumber)
        {
            //判断当前是否有在测试
            if (!this.device.IsAutoMode)
            {
                return;//手动模式不受换型影响
            }
            MessageBox.Show($"LMS系统换型已切换型号{partNumber}，请准备换型！", "换型提示");
            if (IsRunning)
            {
                LogHelper.Log.Info("LMS系统通知换型 请准备停止当前测试");
                UpdateTestStatus(this.lbMessage, $"LMS系统通知换型{partNumber}，请准备停止当前测试！", Color.Lime);
                DebugTestStop();
            }
            UpdateTestStatus(this.lbMessage, $"LMS系统通知切换型号！{partNumber}", Color.Lime);
            
            this.cbPartNumber.Text = partNumber;

            var testDir = "";
            if (!string.IsNullOrEmpty(this.basicEntity.TestActualProfile))
            {
                testDir = System.IO.Path.GetDirectoryName(this.basicEntity.TestActualProfile);
                this.basicEntity.TestActualProfile = testDir + "\\" + partNumber + ".tp";
                this.basicEntity.TestPlanName = partNumber;
                LogHelper.Log.Info($"换型型号-planName={this.basicEntity.TestPlanName}");
                if (!File.Exists(this.basicEntity.TestActualProfile))
                {
                    UpdateTestStatus(this.lbMessage, $"换型失败！{partNumber}读取测试计划失败！", Color.Lime);
                    return;
                }
                LoadTestPlan();//查询是否匹配
            }
            else
            {
                return;
            }
            UpdateTestStatus(this.lbMessage, $"已切换产品型号:{partNumber}", Color.Lime);
            LogHelper.Log.Info($"已切换产品型号 Running={IsRunning}");
            if (this.IsRunning)
                ;// UseAtutoTest();
            else
                AutoStartTest();
        }

        public void UpdateLMSState(bool state)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(() =>
                {
                    if (state)
                    {
                        this.btnLMSControl.BackColor = Color.Lime;
                        this.lbxLMS.Text = "ON";
                    }
                    else
                    {
                        this.btnLMSControl.BackColor = Color.Red;
                        this.lbxLMS.Text = "OFF";
                    }
                }));
            }
            else
            {
                if (state)
                {
                    this.btnLMSControl.BackColor = Color.Lime;
                    this.lbxLMS.Text = "ON";
                }
                else
                {
                    this.btnLMSControl.BackColor = Color.Red;
                    this.lbxLMS.Text = "OFF";
                }
            }
        }

        #endregion
    }
}
